package cn.maihe.elg.operation.utils;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.bouncycastle.util.encoders.Base64;
import org.junit.Test;
import org.springframework.data.util.Pair;
import org.springframework.util.Base64Utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * RSA公钥/私钥/签名工具包
 * </p>
 * <p>
 * 罗纳德·李维斯特（Ron [R]ivest）、阿迪·萨莫尔（Adi [S]hamir）和伦纳德·阿德曼（Leonard [A]dleman）
 * </p>
 * <p>
 * 字符串格式的密钥在未在特殊说明情况下都为BASE64编码格式<br/>
 * 由于非对称加密速度极其缓慢，一般文件不使用它来加密而是使用对称加密，<br/>
 * 非对称加密算法可以用来对对称加密的密钥加密，这样保证密钥的安全也就保证了数据的安全
 * </p>
 *
 * @author IceWee
 * @version 1.0
 * @date 2012-4-26
 */
@Slf4j
public class RsaUtil {

    /**
     * 加密算法RSA
     */
    public static final String KEY_ALGORITHM = "RSA";

    /**
     * 签名算法
     */
    public static final String SIGNATURE_ALGORITHM = "MD5withRSA";

    /**
     * 获取公钥的key
     */
    private static final String PUBLIC_KEY = "RSAPublicKey";

    /**
     * 获取私钥的key
     */
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 245;

    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 256;

    //签名算法名称
    private static final String RSA_KEY_ALGORITHM = "RSA";
    //标准签名算法名称
    private static final String RSA_SIGNATURE_ALGORITHM = "SHA1withRSA";
    private static final String RSA2_SIGNATURE_ALGORITHM = "SHA256withRSA";
    //RSA密钥长度,默认密钥长度是1024,密钥长度必须是64的倍数，在512到65536位之间,不管是RSA还是RSA2长度推荐使用2048
    private static final int KEY_SIZE = 2048;


    /**
     * <p>
     * 用私钥对信息生成数字签名
     * </p>
     *
     * @param data       已加密数据
     * @param privateKey 私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static String sign(byte[] data, String privateKey) throws Exception {
        byte[] keyBytes = Base64Util.decode(privateKey);
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initSign(privateK);
        signature.update(data);
        return new String(Base64Util.encode(signature.sign()), "utf-8");
    }

    /**
     * <p>
     * 校验数字签名
     * </p>
     *
     * @param data      已加密数据
     * @param publicKey 公钥(BASE64编码)
     * @param sign      数字签名
     * @return
     * @throws Exception
     */
    public static boolean verify(byte[] data, String publicKey, String sign)
            throws Exception {
        byte[] keyBytes = Base64Util.decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        PublicKey publicK = keyFactory.generatePublic(keySpec);
        Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
        signature.initVerify(publicK);
        signature.update(data);
        return signature.verify(Base64Util.decode(sign));
    }

    /**
     * 大数据分段解密
     * @param privateKey
     * @param encryptedData
     * @return
     * @throws Exception
     */
    public static byte[] decryptLargeData(PrivateKey privateKey, byte[] encryptedData) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);

        int keySize = ((RSAKey) privateKey).getModulus().bitLength();
        int blockSize = keySize / 8; // RSA解密块大小

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        for (int i = 0; i < encryptedData.length; i += blockSize) {
            int length = Math.min(blockSize, encryptedData.length - i);
            byte[] block = Arrays.copyOfRange(encryptedData, i, i + length);
            byte[] decryptedBlock = cipher.doFinal(block);
            outputStream.write(decryptedBlock);
        }

        return outputStream.toByteArray();
    }

    /**
     * 大数据分段加密
     * @param publicKey
     * @param data
     * @return
     * @throws Exception
     */
    public static byte[] encryptLargeData(PublicKey publicKey, byte[] data) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        int keySize = ((RSAKey) publicKey).getModulus().bitLength();
        int blockSize = keySize / 8 - 11; // PKCS1Padding需要11字节填充

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        for (int i = 0; i < data.length; i += blockSize) {
            int length = Math.min(blockSize, data.length - i);
            byte[] block = Arrays.copyOfRange(data, i, i + length);
            byte[] encryptedBlock = cipher.doFinal(block);
            outputStream.write(encryptedBlock);
        }

        return outputStream.toByteArray();
    }

    /**
     * <P>
     * 私钥解密
     * </p>
     *
     * @param encryptedData 已加密数据
     * @param privateKey    私钥(BASE64编码)
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(byte[] encryptedData, PrivateKey privateKey) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
            throw new RuntimeException("私钥初始化异常：" + e.getMessage(), e);
        }
        int inputLen = encryptedData.length;
        byte[] decryptedData = new byte[0];
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();) {
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            decryptedData = out.toByteArray();
        } catch (IllegalBlockSizeException | BadPaddingException | IOException e) {
            throw new RuntimeException("私钥分段解密异常：" + e.getMessage(), e);
        }
        return decryptedData;
    }

    /**
     * 公钥加密
     */
    public static byte[] encryptByPublicKey(byte[] data, PublicKey publicKey) {
        // 对数据加密
        Cipher cipher = null;
        int inputLen = data.length;
        try {
            cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
            throw new RuntimeException("公钥初始化异常：" + e.getMessage(), e);
        }
        byte[] encryptedData = new byte[0];
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();) {
            int offSet = 0;
            byte[] cache;
            int i = 0;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(data, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            encryptedData = out.toByteArray();
        } catch (IllegalBlockSizeException | BadPaddingException | IOException e) {
            throw new RuntimeException("公钥分段加密异常：" + e.getMessage(), e);
        }
        return encryptedData;
    }


    /**
     * <p>
     * 生成密钥对(公钥和私钥)
     * </p>
     *
     * @return
     * @throws Exception
     */
    public static Pair<RSAPublicKey, RSAPrivateKey> genKeyPair() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        return Pair.of(publicKey, privateKey);
    }

    /**
     * <p>
     * 获取私钥
     * </p>
     *
     * @param keyPair 密钥对
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Pair<RSAPublicKey, RSAPrivateKey> keyPair)
            throws Exception {
        Key key = keyPair.getSecond();
        return new String(Base64Util.encode(key.getEncoded()), "utf-8");
    }

    /**
     * <p>
     * 获取公钥
     * </p>
     *
     * @param keyPair 密钥对
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Pair<RSAPublicKey, RSAPrivateKey> keyPair)
            throws Exception {
        Key key = (Key) keyPair.getFirst();
        return new String(Base64Utils.encode(key.getEncoded()), "utf-8");
    }

    /**
     * 生成密钥对
     *
     * @return 返回包含公私钥的map
     */
    public static Map<String, String> generateKey() {
        KeyPairGenerator keygen;
        try {
            keygen = KeyPairGenerator.getInstance(RSA_KEY_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("RSA初始化密钥出现错误,算法异常");
        }
        SecureRandom secrand = new SecureRandom();
        //初始化随机产生器
        secrand.setSeed("Alian".getBytes());
        //初始化密钥生成器
        keygen.initialize(KEY_SIZE, secrand);
        KeyPair keyPair = keygen.genKeyPair();
        //获取公钥并转成base64编码
        byte[] pub_key = keyPair.getPublic().getEncoded();
        String publicKeyStr = Base64.toBase64String(pub_key);
        //获取私钥并转成base64编码
        byte[] pri_key = keyPair.getPrivate().getEncoded();
        String privateKeyStr = Base64.toBase64String(pri_key);
        //创建一个Map返回结果
        Map<String, String> keyPairMap = new HashMap<>();
        keyPairMap.put("publicKeyStr", publicKeyStr);
        keyPairMap.put("privateKeyStr", privateKeyStr);
        return keyPairMap;
    }

    /**
     * 公钥加密(用于数据加密)
     *
     * @param data         加密前的字符串
     * @param publicKeyStr base64编码后的公钥
     * @return base64编码后的字符串
     * @throws Exception
     */
    public static String encryptByPublicKey(String data, String publicKeyStr) throws Exception {
        //Java原生base64解码
        byte[] pubKey = Base64.decode(publicKeyStr);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //根据转换的名称获取密码对象Cipher（转换的名称：算法/工作模式/填充模式）
        Cipher cipher = Cipher.getInstance(RSA_KEY_ALGORITHM);
        //用公钥初始化此Cipher对象（加密模式）
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        //对数据加密
        byte[] encrypt = cipher.doFinal(data.getBytes());
        //返回base64编码后的字符串
        return URLEncoder.encode(Base64.toBase64String(encrypt), "UTF-8");
    }

    /**
     * 公钥分段加密(用于数据加密)
     *
     * @param data         加密前的字符串
     * @param publicKeyStr base64编码后的公钥
     * @return base64编码后的字符串
     * @throws Exception
     */
    public static String encryptSegment(String data, String publicKeyStr) {
        try {
            byte[] decoded =  Base64.decode(publicKeyStr);
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(RSA_KEY_ALGORITHM)
                    .generatePublic(new X509EncodedKeySpec(decoded));
            Cipher cipher = Cipher.getInstance(pubKey.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            //分段加密
            // URLEncoder编码解决中文乱码问题
            byte[] plainText = data.getBytes("UTF-8");
            int inputLen = plainText.length;
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            //对数据分段解密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    cache = cipher.doFinal(plainText, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(plainText, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            out.close();
            String outStr = URLEncoder.encode(Base64.toBase64String(decryptedData), "UTF-8");
            return outStr;
        } catch (Exception e) {
            log.error("[公钥分段加密失败, {}", e.getMessage());
            throw new RuntimeException("[公钥分段加密]失败");
        }
    }

    /**
     * 公钥分段解密(用于数据解密)
     *
     * @param encryptData   解密前的字符串
     * @param privateKeyStr base64编码后的私钥
     * @return base64编码后的字符串
     * @throws Exception
     */
    public static String decryptSegment(String encryptData, String privateKeyStr) {
        try {
            byte[] decoded = Base64.decode(privateKeyStr);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance(RSA_KEY_ALGORITHM)
                    .generatePrivate(new PKCS8EncodedKeySpec(decoded));
            Cipher cipher = Cipher.getInstance(priKey.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            // 分段解密
            // URLEncoder编码解决中文乱码问题
            byte[] data = Base64.decode(URLDecoder.decode(encryptData, "UTF-8"));

            // 加密时超过117字节就报错。为此采用分段加密的办法来加密
            byte[] enBytes = null;
            for (int i = 0; i < data.length; i += MAX_DECRYPT_BLOCK) {
                // 注意要使用2的倍数，否则会出现加密后的内容再解密时为乱码
                byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(data, i, i + MAX_DECRYPT_BLOCK));
                enBytes = ArrayUtils.addAll(enBytes, doFinal);
            }
            String outStr = new String(enBytes,"UTF-8");
            return outStr;
        } catch (Exception e) {
            log.error("[私钥分段解密失败, {}", e.getMessage());
            throw new RuntimeException("[私钥分段解密]失败");
        }
    }

    /**
     * 私钥解密(用于数据解密)
     *
     * @param data          解密前的字符串
     * @param privateKeyStr 私钥
     * @return 解密后的字符串
     * @throws Exception
     */
    public static String decryptByPrivateKey(String data, String privateKeyStr) {
        try {
            //Java原生base64解码
            byte[] priKey = Base64.decode(privateKeyStr);
            //创建PKCS8编码密钥规范
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
            //返回转换指定算法的KeyFactory对象
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
            //根据PKCS8编码密钥规范产生私钥对象
            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
            //根据转换的名称获取密码对象Cipher（转换的名称：算法/工作模式/填充模式）
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            //用私钥初始化此Cipher对象（解密模式）
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            //对数据解密
            byte[] decrypt = cipher.doFinal(Base64.decode(URLDecoder.decode(data, "UTF-8")));
//            byte[] decrypt = cipher.doFinal(Base64.decode(data.replace("\r\n", "")));
            //返回字符串
            return new String(decrypt);
        } catch (Exception e) {
            log.error("[私钥解密]失败, {}", e.getMessage());
            throw new RuntimeException("[私钥解密]失败");
        }
    }

    /**
     * 私钥加密(用于数据签名)
     *
     * @param data          加密前的字符串
     * @param privateKeyStr base64编码后的私钥
     * @return base64编码后后的字符串
     * @throws Exception
     */
    public static String encryptByPrivateKey(String data, String privateKeyStr) throws Exception {
        //Java原生base64解码
        byte[] priKey = Base64.decode(privateKeyStr);
        //创建PKCS8编码密钥规范
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据PKCS8编码密钥规范产生私钥对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //根据转换的名称获取密码对象Cipher（转换的名称：算法/工作模式/填充模式）
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用私钥初始化此Cipher对象（加密模式）
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        //对数据加密
        byte[] encrypt = cipher.doFinal(data.getBytes());
        //返回base64编码后的字符串
        return Base64.toBase64String(encrypt);
    }

    /**
     * 公钥解密(用于数据验签)
     *
     * @param data         解密前的字符串
     * @param publicKeyStr base64编码后的公钥
     * @return 解密后的字符串
     * @throws Exception
     */
    public static String decryptByPublicKey(String data, String publicKeyStr) throws Exception {
        //Java原生base64解码
        byte[] pubKey = Base64.decode(publicKeyStr);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //根据转换的名称获取密码对象Cipher（转换的名称：算法/工作模式/填充模式）
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        //用公钥初始化此Cipher对象（解密模式）
        cipher.init(Cipher.DECRYPT_MODE, publicKey);
        //对数据解密
        byte[] decrypt = cipher.doFinal(Base64.decode(data));
        //返回字符串
        return new String(decrypt);
    }

    /**
     * RSA签名
     *
     * @param data     待签名数据
     * @param priKey   私钥
     * @param signType RSA或RSA2
     * @return 签名
     * @throws Exception
     */
    public static String sign(byte[] data, byte[] priKey, String signType) throws Exception {
        //创建PKCS8编码密钥规范
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(priKey);
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //根据PKCS8编码密钥规范产生私钥对象
        PrivateKey privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
        //标准签名算法名称(RSA还是RSA2)
        String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM;
        //用指定算法产生签名对象Signature
        Signature signature = Signature.getInstance(algorithm);
        //用私钥初始化签名对象Signature
        signature.initSign(privateKey);
        //将待签名的数据传送给签名对象(须在初始化之后)
        signature.update(data);
        //返回签名结果字节数组
        byte[] sign = signature.sign();
        //返回Base64编码后的字符串
        return Base64.toBase64String(sign);
    }

    /**
     * RSA校验数字签名
     *
     * @param data     待校验数据
     * @param sign     数字签名
     * @param pubKey   公钥
     * @param signType RSA或RSA2
     * @return boolean 校验成功返回true，失败返回false
     */
    public static boolean verify(byte[] data, byte[] sign, byte[] pubKey, String signType) throws Exception {
        //返回转换指定算法的KeyFactory对象
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_KEY_ALGORITHM);
        //创建X509编码密钥规范
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(pubKey);
        //根据X509编码密钥规范产生公钥对象
        PublicKey publicKey = keyFactory.generatePublic(x509KeySpec);
        //标准签名算法名称(RSA还是RSA2)
        String algorithm = RSA_KEY_ALGORITHM.equals(signType) ? RSA_SIGNATURE_ALGORITHM : RSA2_SIGNATURE_ALGORITHM;
        //用指定算法产生签名对象Signature
        Signature signature = Signature.getInstance(algorithm);
        //用公钥初始化签名对象,用于验证签名
        signature.initVerify(publicKey);
        //更新签名内容
        signature.update(data);
        //得到验证结果
        return signature.verify(sign);
    }

    public static String encrypt(String data, String publicKeyStr) throws Exception {
        byte[] decodedKey = Base64.decode(publicKeyStr);
        PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decodedKey));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedData = cipher.doFinal(data.getBytes("UTF-8"));
        return Base64.toBase64String(encryptedData);
    }

    public static String decrypt(String encryptedData, String privateKeyStr) throws Exception {
        byte[] decodedKey = Base64.decode(privateKeyStr);
        PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decodedKey));
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedData = cipher.doFinal(Base64.decode(encryptedData));
        return new String(decryptedData, "UTF-8");
    }

    @Test
    public void testEncrypt() throws Exception {
        String privateKeyPEM = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDU2SE5TFYFWbqrf/ocLlyFBH2uHF2svzgQ5dFXpcz4XOXCHFdyfr2VNsi5/QtSYFQ+Vy6RjCKXGos50Qlg1JDrQuCGHFHbwyKl507hADZMHlavE5f4MYJxhDc2dzTRyLpBbuy2keiXtnyyxqZ9+YSnkIoQEEtr2/Au24bVE3OJh0ZpVUa12y6Yca4DPpeVIRzKP4v4V+RIb+OmyOdWSqbf9MFYhOtuI2P+KNJgIPTCnWYt1KfNd1onwg0U+WmGquPlqlJRPNSvhsX+yt58rQgm4NXixECcVD9Er2gCqgmlBPonztPVLBQW/R33rJwP5vLzBq3h/nfclvHyviLS4y+TAgMBAAECggEBAMYSJNvIUMh73r2Xw20UK57RNg+fcADAlXEMHIqezSZWdKz1aN8wWEYSDCsf8rg+0kaNJNXm/Y118xfjkgGc7hswSfYjRn3mkkim/v1dECo3lV0pM6OQlx4B9stllS6fx8v6aKfhEfyUomhPekICv9KbLA+UykreCh3gxhFlH4BbQrq7JFadAR1gKBOvaaQBSXgS34s1k97meBJxITp5/CbTMhLCI8dG5SM63iFuzy8tEITcmMTdl/wuV2Uo9MiM7uTJ3I6HE0jtq3/TFk2aEtJfo378BWNywCxFO0jgYVGYXLbOyNyJhARwq/saiMcahCxU728Nx3CpnE38029KLOECgYEA7nbmoL3rlEJov+3xGUkyu5dJevWBZxVXZql8+tRTxkUNLsePnAvSMCuwFKctj2Q3okJprrAK+31c2XbJp590u/ES1Bur0R0v02MExgk7bH2Vynhp/RMtC4CB6kDnbOnA5TFHvwH1xWrQwrczHjaBO+PutfJB8RHIfry8pPOsa1ECgYEA5IAAZcvfRFNIyEFFS0XYTWwugUe5cxoxqEJDNxafPbi7O8jw4jCRhD1TfW0jS+xALl8XUPCQ6jQlqO9auGOlmMJWxL16eToCZ+m5q4dAMSLzYdMvlcgopMH1rFdwsNRtg+e//WSBv60/yRM0kCPGDatD9eNZLwW8j1hWa5dAa6MCgYEAqGgKCdz2YRbhOSJGEbBzBq4Z858sCuu0dMkffViz7SLY43+FuRNUFjbUPFGwSELjU1EJp5eluePXzbApS5q96viebnM4TQ8KtoOIXH8qmzy5q2qMl3CScDwKA7Bgf7c5ReMeoxM0SX5c/hY5II4niG85Jv92eFQxvud1Zhy8WHECgYB3CCcs4FNiaHBVwYqzd6MCUgS33AFDcLXFjR8up1407PK8ZiT1748ecEP55syoVF3qyiZ/R5J2LswfgPCldWNifHpu6rXOSOXP8/WA4WgTML3QjA8R278wdMniCXru4vpZ6HQfMChXDY1Y1eRf4gLeRAWXJePjlv1vPvll+tjYOQKBgAkD6XxRr7w7quYwOu8vO+geK3j0+oqUhAzB8pxdrTmNGlrhHMIJmaaiM3WlAvy0aPCRWB7IXaLl0UE3OJLoq9mWkg4YwD/lPJmZ29WRvaqpKx8DQMFesHW808ud0qf+xg2StZD4L4Rp8YmqIPGGGxmT0EmcuNTXZ2m6qDwVvfuw";
        String publicKeyPEM = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1NkhOUxWBVm6q3/6HC5chQR9rhxdrL84EOXRV6XM+FzlwhxXcn69lTbIuf0LUmBUPlcukYwilxqLOdEJYNSQ60LghhxR28MipedO4QA2TB5WrxOX+DGCcYQ3Nnc00ci6QW7stpHol7Z8ssamffmEp5CKEBBLa9vwLtuG1RNziYdGaVVGtdsumHGuAz6XlSEcyj+L+FfkSG/jpsjnVkqm3/TBWITrbiNj/ijSYCD0wp1mLdSnzXdaJ8INFPlphqrj5apSUTzUr4bF/srefK0IJuDV4sRAnFQ/RK9oAqoJpQT6J87T1SwUFv0d96ycD+by8wat4f533Jbx8r4i0uMvkwIDAQAB";
        privateKeyPEM = "";
        publicKeyPEM = "";
        Map hashMap = new HashMap();
        hashMap.put("method", "get_access_token");
        hashMap.put("api_key", "test");
        hashMap.put("api_secret", "test");
        hashMap.put("timestamp", DateUtil.format(new Date(), "yyyyMMddHHmmss"));
        hashMap.put("sign", "7F3F5F6E763B3B937097F409FBB5628B");
        String data = JSONObject.toJSONString(hashMap);

        data = "{\"api_key\":\"7e065f2520a4d7567636ca257e8b668085944ea443beda0840c633ae87a1ea59\",\"api_secret\":\"eb3d3b09a32cd7ac5c33f397ed462dd82fbba4b6bdf673a52a94e249a587d6ef\",\"method\":\"get_access_token\",\"sign\":\"A38BE1217F949F7ED8C3D21996B7B423\",\"timestamp\":\"20250220224032\"}";
//        data = "{\"guarantee_no\":\"FZ20240909100250887\",\"serial_num\":\"806097220746717\",\"timestamp\":\"20240910143451\",\"sign\":\"7F3F5F6E763B3B937097F409FBB5628B\"}";
//        String ciphertext = RsaUtil.encrypt(data, publicKeyPEM);
        String ciphertext = RsaUtil.encryptSegment(data, publicKeyPEM);
        System.out.println("ciphertext：" + ciphertext);
//        String decryptedText = RsaUtil.decryptByPrivateKey(ciphertext, privateKeyPEM);
        String decryptedText = RsaUtil.decryptSegment(ciphertext, privateKeyPEM);
        System.out.println(decryptedText);
    }

    @Test
    public void testDecrypt() throws Exception {
        String privateKeyPEM = "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDQQ/iHprUgPjFx" +
                "NdPenbi+CuU/GinEqXmPgiIHR76pI6i8EaqPeYtUXAYdyS6slA+DE4HS3O6C4jGr" +
                "BB8ILbo60CWikhVffQkV0XOPBW2tEn9BTe+0P8GupussQBiOOjiNOBkh+vMdu6yB" +
                "5HJIirl4F0f20qX/WLzwHBMJWGMObm8IK0jDnYZjSWG4CFtAECAJkA4nWM3V25Vs" +
                "fYjMYJC0ahbtrxX0pxBfNeBCQfUipKjQ0LBdmbj1lMGTi+nG6glHDDnsZpQlT5Yy" +
                "gpy/txQLr5TZsDopoFu/OBmH/xgLHteZJslw+jr3XRWh0saMFW4z+rNc18M02nUx" +
                "QWMfW6DXAgMBAAECggEAUhvaKjERi+q5N3cPVt877MEC7MP137EpWejmXZRtmOWU" +
                "KsGUSwiSY+n8B1Y/7o5ZJ0ZTkrzD1Bo1lsUDLwhIOdPCYrvRbVowcMepFaQAP5Hh" +
                "Ve/SJ3BTffYVFdcXV0ug7BxH3FvB6eEJ/BQC8pKu2KflGWynQWrM4qVO5ApS02cE" +
                "RUQWT7aLLqIASD1wqxv6y7E/9alL1xqiOiB/+2v6nOSOn64k8P/wBGAvoH8CJVAA" +
                "llo4toC41hK1WUHrwDNZ10fLMHBo4e6PKg5K1YQPP5k+05MLno9XW0+PvfplqAzq" +
                "TS5EiXP2j6rmppjU2ZTyIycF6DIyS9XOU8VCd+j48QKBgQD0f12OPzNdOwB1xGxK" +
                "FyklVZ0P5Pj/nf0l772evvErBNSLJVIPJlJvfaXzle8kqWpYUWSwnlxIATQNEcLv" +
                "/6KQuJ2AgG4ZnjMypsMn56H8m2QcC2TgicO1LawjrRulqRm2cOLFQQCxbcr/3vgb" +
                "wrsxafWnNcXMC0/dNY0xuJwitQKBgQDaED2sDb/V1xaAVGmWVg5VmeQYXhByw7RB" +
                "HGDbXqkPjtEtLgfQBhpwcsAYvJYA1zZpZxSAdo+z+8YHZY4ImXRGI4ewAcgnmGpk" +
                "h9RppmpKtJhLH1KC9s3UTAEKlj7IBbFTOxXE5gmCNY6dNPp1BbGMbYIYJh407X+i" +
                "Sqdt4ygw2wKBgG6wcsSBbFma6pxmbrgkQCZ82fxmJyxidEcGgIwr2bcmGqtcHAhr" +
                "ywpakhTzHi8028ZcIv+q0hBvKwd3sQ9CZnCqg/O3MSE78+XMhbG9NiLMnsfriKH2" +
                "/Lk7kiEcr9WR9ugXtzKiORQaprqsURsQT/sRA3vN5lx4CpIVOnT2JQm5AoGAMPma" +
                "0EyaPC29iP7sY+5Z89HHT824hf38Ou9jtYEyGSNrSWlgKdFlGMI88JFSY0fymYOk" +
                "MCHwrmyqkji1yKqmWaZbMCWGTZZGtuNmyn+subCLz7tuLam+mqKjTTxnR0c4B0hq" +
                "4DkGA6+Boz8lzSiFMtPZdxEAkcSReOKpbd2pxicCgYBK/NPXPKDC094kLIBwWimM" +
                "UNf9CPofY1xs8SKtic6GTM57OhfhIT/9MSAKbafI2js68zWpqmbQSKwZUNvt4VLo" +
                "Eju8enpA+LimfTRwUlt8Vm5jWvwV6Ljv9oyVaowyBDRTI3d4Reo/ovcUn7CHqC/q" +
                "Cq6z0QPz0Me0phIQ7ylhkg==";
        privateKeyPEM="MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDU2SE5TFYFWbqrf/ocLlyFBH2uHF2svzgQ5dFXpcz4XOXCHFdyfr2VNsi5/QtSYFQ+Vy6RjCKXGos50Qlg1JDrQuCGHFHbwyKl507hADZMHlavE5f4MYJxhDc2dzTRyLpBbuy2keiXtnyyxqZ9+YSnkIoQEEtr2/Au24bVE3OJh0ZpVUa12y6Yca4DPpeVIRzKP4v4V+RIb+OmyOdWSqbf9MFYhOtuI2P+KNJgIPTCnWYt1KfNd1onwg0U+WmGquPlqlJRPNSvhsX+yt58rQgm4NXixECcVD9Er2gCqgmlBPonztPVLBQW/R33rJwP5vLzBq3h/nfclvHyviLS4y+TAgMBAAECggEBAMYSJNvIUMh73r2Xw20UK57RNg+fcADAlXEMHIqezSZWdKz1aN8wWEYSDCsf8rg+0kaNJNXm/Y118xfjkgGc7hswSfYjRn3mkkim/v1dECo3lV0pM6OQlx4B9stllS6fx8v6aKfhEfyUomhPekICv9KbLA+UykreCh3gxhFlH4BbQrq7JFadAR1gKBOvaaQBSXgS34s1k97meBJxITp5/CbTMhLCI8dG5SM63iFuzy8tEITcmMTdl/wuV2Uo9MiM7uTJ3I6HE0jtq3/TFk2aEtJfo378BWNywCxFO0jgYVGYXLbOyNyJhARwq/saiMcahCxU728Nx3CpnE38029KLOECgYEA7nbmoL3rlEJov+3xGUkyu5dJevWBZxVXZql8+tRTxkUNLsePnAvSMCuwFKctj2Q3okJprrAK+31c2XbJp590u/ES1Bur0R0v02MExgk7bH2Vynhp/RMtC4CB6kDnbOnA5TFHvwH1xWrQwrczHjaBO+PutfJB8RHIfry8pPOsa1ECgYEA5IAAZcvfRFNIyEFFS0XYTWwugUe5cxoxqEJDNxafPbi7O8jw4jCRhD1TfW0jS+xALl8XUPCQ6jQlqO9auGOlmMJWxL16eToCZ+m5q4dAMSLzYdMvlcgopMH1rFdwsNRtg+e//WSBv60/yRM0kCPGDatD9eNZLwW8j1hWa5dAa6MCgYEAqGgKCdz2YRbhOSJGEbBzBq4Z858sCuu0dMkffViz7SLY43+FuRNUFjbUPFGwSELjU1EJp5eluePXzbApS5q96viebnM4TQ8KtoOIXH8qmzy5q2qMl3CScDwKA7Bgf7c5ReMeoxM0SX5c/hY5II4niG85Jv92eFQxvud1Zhy8WHECgYB3CCcs4FNiaHBVwYqzd6MCUgS33AFDcLXFjR8up1407PK8ZiT1748ecEP55syoVF3qyiZ/R5J2LswfgPCldWNifHpu6rXOSOXP8/WA4WgTML3QjA8R278wdMniCXru4vpZ6HQfMChXDY1Y1eRf4gLeRAWXJePjlv1vPvll+tjYOQKBgAkD6XxRr7w7quYwOu8vO+geK3j0+oqUhAzB8pxdrTmNGlrhHMIJmaaiM3WlAvy0aPCRWB7IXaLl0UE3OJLoq9mWkg4YwD/lPJmZ29WRvaqpKx8DQMFesHW808ud0qf+xg2StZD4L4Rp8YmqIPGGGxmT0EmcuNTXZ2m6qDwVvfuw";
        byte[] privateKeyBytes = Base64.decode(privateKeyPEM);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        PrivateKey privateKey = java.security.KeyFactory.getInstance("RSA").generatePrivate(keySpec);

        String ciphertext = "YdworBH%2FDWhXhV97n3jFcoB4SGvmjDnT%2Byg%2BFXejhFNshlqxhFLCR%2BCxPW5i3esllGD5MlAo73bcy8phK%2BL%2BYdarFY0LTnkxhKmprLTiRSxpF5qY3jCRhxHm%2FxBEZoBdcfczPezqUX88K0YHQecsnDaNVqa1oZdnxSFD%2BKM4RNCgELN5Ig0SOU0bNkV%2BxtC7F3CwyjuUHzenRTHJVzbac8KNmtEPVcHA6WxCgvLmPm3Gf9PY9BOy02KrXBrT%2BvZXJtqRY05tce%2FVMcAiQWJ6ZjIg89mc5IGRxFVMYn3kpNAA2FepG6iCV0IiHTmT2nKT%2Fcnw%2Frsoj4WNE9mW6%2BkiEQ%3D%3D";
        ciphertext="ntjgkMi0YDbay5%2Fz1aFR7bTJjKlmU36AtgqmOn%2BixNaJTr5rYl1PkLUgWSCG9u%2FD69OMJKL4OLmumRIsXfM92XBjQcQkwgLN%2BokLoCxaTTgXDuii3S%2Fqa2orSmvtdMjFMtdxuV4uG1V%2FsnydYzCE85UF5dmYc4P%2BqNt4Jcao4zU7ExtwiRZuM2kMfMBqzoXoQmfpOWmTPwAf%2BWqCmXB%2FWBjn9TPGSxuLFm1AvlIopY3RT4raIgJ330pPLhbh0VhjWb6mj2DLJ37f8ftKoR5OBTia3IcCFkJJasF2iTFNGiaGtkoip78pyqDkOZTWe72nl47B2%2B0k61PFYbzsFa2k5A%3D%3D";
//        ciphertext = URLDecoder.decode(ciphertext, "UTF-8");
//
//        byte[] encryptedBytes = Base64.decode(ciphertext);
//
//        // 创建 RSA 解密器
//        Cipher cipher = Cipher.getInstance("RSA");
//        cipher.init(Cipher.DECRYPT_MODE, privateKey);
//        // 解密
//        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
//        String decryptedText = new String(decryptedBytes);

//        String decryptedText = RsaUtil.decryptByPrivateKey(ciphertext, privateKeyPEM);
        String decryptedText = RsaUtil.decryptSegment(ciphertext, privateKeyPEM);
        System.out.println(decryptedText);

    }

    @Test
    public void encodeAndDecode() throws Exception {
        String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqWTjtjc6FUpJu/YdTf0z" +
                "WOCE4d4PrzkVpy3IMrpzV6S1LDCxc3PfMpx6jrLlNxTEKtyCs0h9dxfGQRiCkDpp" +
                "czG8fkqJ+O6ozPPFgeHL4mUHVYx1+uO+eMAf+v7pPMobbKgX74f74G4XsQJqBndt" +
                "2FYiE0c4T0tYeUG240syjIr3dJgN8U2NE098+j+NtIuuxxRrbVLg0/dfb/aTGS2I" +
                "BAA3s4IMrDiU+KPaREheW9c3NBhNuG/ljxV+DUsKaH+6o8B/ThfIUZ5bnpFw+TpA" +
                "EFb/JvyWRloIjaOtaW3G5qyYjWA2jNTeOHQqPHrDTAD077J69nVhQKPYsLoiLMMG" +
                "nQIDAQAB";
        String privateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCpZOO2NzoVSkm7" +
                "9h1N/TNY4ITh3g+vORWnLcgyunNXpLUsMLFzc98ynHqOsuU3FMQq3IKzSH13F8ZB" +
                "GIKQOmlzMbx+Son47qjM88WB4cviZQdVjHX64754wB/6/uk8yhtsqBfvh/vgbhex" +
                "AmoGd23YViITRzhPS1h5QbbjSzKMivd0mA3xTY0TT3z6P420i67HFGttUuDT919v" +
                "9pMZLYgEADezggysOJT4o9pESF5b1zc0GE24b+WPFX4NSwpof7qjwH9OF8hRnlue" +
                "kXD5OkAQVv8m/JZGWgiNo61pbcbmrJiNYDaM1N44dCo8esNMAPTvsnr2dWFAo9iw" +
                "uiIswwadAgMBAAECggEAefuXJ26Zux8l/d77t1+wjD4SMvzQWqRG/X6wfidaTDDl" +
                "7o6aGsPEZRPeBci523Ju2Va2IBkBkLNkJxhZXTdTHIsia+eNd9+VWxHoluFdCwkp" +
                "wOdHRoaecSIZZYwPtaDtIs/hfLJ2JWXiVauhYkq6pWFRZISS/jcJ3Tf/VaqfGikE" +
                "k51TTDejOi2kp6DPyacnEV3fJ4Rs3r6wGdtpZ7uDrF+4btDoXzGZu3uH0xNC1qew" +
                "b667BtVYQ65L+TbeEcd2UdffAirRXyDLgHL8PeGEbgu6FAhLceNYw5LJzEd+BYZZ" +
                "mDbGFco4BrQnI9GFVEz7NYkp5VQyjKV6mQqKMvHcWQKBgQDUVf+edCvczQLSLUlr" +
                "rpanyCEe1clqHzbHqDIHKqx9uUy92A2pscJqfLPXFRB8ymwGsnHTmw4HQMODuC10" +
                "o4iLpwpy3FnhbHVVgIgTBdFUCjTG95AFY+cfAXHOBIDPsZcbApgcJYiM4KQKD6cV" +
                "QJub6eN/2h2XdMIao8GO61xF+wKBgQDMOk3NKP5pQlW+PuYZ+1S+Id4hWg8TbAjz" +
                "Nh0p9eBUKYHF6mAXxg/VrwohHPQsi3h+vaYdepq12FYJhgR+3S7FvxEnC6IswEi+" +
                "EwW6mF4i9DitB02VoqdGrg50YCJiOcH93rTNKuanf92tPiCPMP8Lvl3toj/mWJHC" +
                "DRLEt9Z6RwKBgEHuykbrj8sqJZwZz9iOB93leNNYUwiO1LW+dnpfN9x6M2gntGZi" +
                "+hmSy00YD1yQhma19j5cwUhjRdKa2BKFzRqALfBol8g1o2F/XcF6ZvuPh7/Yk3H5" +
                "CYVJL4tnPpA/dso+Tfk/dl04S/eL0Lf6rdcGE0xZ8CJdcQBQpQO59ZcNAoGBALE+" +
                "kLNTtqlHxv6bvDwkYoG5Bv3PGXJzurjJ6Dm4iP7CHzzTkp5PaQK9LX9bj5bxXJwy" +
                "n+7Jr2fO36zYQSKRd7xrfMl0UUWhhABipgAxqNGRP3b79Zu+VIsFGMprfKvfELvy" +
                "AtxlNVV9pbhrSPq9PTzF9OL+g5K4n5fYnMdZ/ayVAoGBAMXY6wMpbphHypP87txs" +
                "pOnDGJjylrT5KgWEmuZYtB/H64dG4PLZHDsIsuTG4sttOIuicq+dPUtyz69dKeqg" +
                "EJrb0eYIpG+rJ9mhdLvPUlMiiECjF/6gCQQC/2QI3sHmpkbJ26WbS3cMvbZQVMso" +
                "q0/1VPjDUrha1GRqISLDJ6T/";
        String data = "{\"guarantee_no\":\"FZ20240909100250887\",\"serial_num\":\"806097220746717\",\"timestamp\":\"20240910143451\",\"sign\":\"7F3F5F6E763B3B937097F409FBB5628B\"}";
        data = "{\"order_no\":\"FZ20240909100250887\",\"sign\":\"622EB298FC46BF68786C8111B4C9A2CA\",\"return_url\":\"https://miniwebtool.com/\",\"timestamp\":\"20241015114423\"}";
        data = "{\n" +
                "  \"method\" : \"get_access_token\",\n" +
                "  \"api_key\" : \"7e065f2520a4d7567636ca257e8b668085944ea443beda0840c633ae87a1ea59\",\n" +
                "  \"sign\" : \"184827FF36E691554979B8D314B7C7CE\",\n" +
                "  \"api_secret\" : \"eb3d3b09a32cd7ac5c33f397ed462dd82fbba4b6bdf673a52a94e249a587d6ef\",\n" +
                "  \"timestamp\" : \"20250109231748\"\n" +
                "}";

//        String encryptStr = RsaUtil.encryptByPublicKey(data, publicKey);
        String encryptStr = RsaUtil.encryptSegment(data, publicKey);
        System.out.println("加密结果：" + encryptStr);
//        data = RsaUtil.decryptByPrivateKey(encryptStr, privateKey);
        data = RsaUtil.decryptSegment(encryptStr, privateKey);
        System.out.println(data);
    }
    public static void main(String[] args) throws Exception {
//        // 1. 加载证书和私钥
//        String cerPath = "sm2.crt"; // CER证书文件路径
//        String p12Path = "sm2.p12"; // PKCS12文件路径
//        String p12Password = "123456"; // PKCS12密码
        // 1. 加载证书和私钥
        String cerBase64 = "MIIEpDCCA4ygAwIBAgIPBwADICIRAREAAANpMyV4MA0GCSqGSIb3DQEBCwUAMG0xCzAJBgNVBAYTAkNOMQ8wDQYDVQQIDAbph43luoYxDzANBgNVBAcMBumHjeW6hjESMBAGA1UECgwJaWZ1dHVyZWNhMRIwEAYDVQQLDAnov5Dnu7Tpg6gxFDASBgNVBAMMC1JTQTIwNDhURVNUMB4XDTIyMTEwMTAyNDcyN1oXDTI3MTAzMTAyNDcyN1owgaQxCzAJBgNVBAYTAkNOMRIwEAYDVQQIDAnnpo/lu7rnnIExEjAQBgNVBAcMCeWOpumXqOW4gjEYMBYGA1UECgwP5L+d6K+B5Lq65py65p6EMRgwFgYDVQQLDA/kv53or4HkurrmnLrmnoQxEjAQBgNVBAsMCXVzY2k6Y3NzYzElMCMGA1UEAwwc5rWL6K+VLeS/neivgeS6uuacuuaehOivgeS5pjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALOVxyUNClGgAkFX+A2ke9En50Ch426IzNRbu02QKjWYtNUtoHUiqE1tgQ+bcVgaUjrzsMyOD65O2/Ih5gp3Jjcyg8UsNF5NFjL83LPjYkyssfXsWzjPLGbXv0fAo7lehttboHF+ZUPaq5dW/IxKVctFDuph5kjx021Es9YRGHGazqQPEtydnhCrv1DgHun0lrjMCxLxm17gxXkpx9ZprwKN4fWEmwYXv4fLFEieKhItKanSxowf0tyxYowSo1w660Xp/wx/qxji8qkLZ8hsqCCzYYaGN205LCIGS248oCVU4Draz1iSV86Xkr10ImihAtEfAubV/I9AablIFeziK6kCAwEAAaOCAQcwggEDMB8GA1UdIwQYMBaAFOViSyOeheTxjv3Zi2p9fkIPLxuXMB0GA1UdDgQWBBQfkfHGWaV13MidBsGBKKpupSUKKzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIGwDAwBgkqgRyHhDMGAQEBAf8EIGZmNjVkNmM0NDA2ZjExZWNhNzA3MDAwYzI5MTg4ZTFmMEoGA1UdYwRDWFkyZDVhYzczOWViZWJjM2QwMGViMWJjN2Y4M2YxOTQyNzcwZTc2ZmQ3Y2QwMzI3MjYzOWQwODY3MDk2MmNkY2RmMjAiBgkqgRyHhDMEAQMBAf8EEjkxNTAwMDAwMzIyMzkyMjkyWDANBgkqhkiG9w0BAQsFAAOCAQEAk1gVtzrV6CX3D7mPVjwE111FN+5BZMp2L+SNW707mVrw1s5+xar2r4QnSgsrDkdXMDuaNjbj6L3BcAEYUKHLN+8xe4tIMYxuneLfqJiyyy6lYSwqeuvuIH9yhjFaK5bt4Ix3YQ6QMgv/LI0932uLWAnoSDhNyHOBzQkEgSU7yIFUKGPdFHums/tJVvD6KPR6QgFZC6ENmg+lUvmX6uu19ScaRtR/nuzgkbCsZaMAMk28PpSwJlHqY2Y8vNSXuGiiY9gky3dpoF6qJ4dx/SdugG+lDVq4zGEZoU1JjSCY2hPNUqhVo10Rh/51UwE5UY//u4aSthjBmInGOuIknrpx+w=="; // CER证书文件路径
        String p12Base64 = "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"; // PKCS12文件路径
        String p12Password = "111111"; // PKCS12密码

        // 加载公钥
        PublicKey publicKey = loadFromRSACer(cerBase64);
        System.out.println("公钥算法: " + publicKey.getAlgorithm());

        // 加载私钥
        PrivateKey privateKey = loadFromRSAP12(p12Base64, p12Password);
        System.out.println("私钥算法: " + privateKey.getAlgorithm());

        // 2. 准备测试数据
        String originalText = "这是一段需要加密的敏感数据";
        System.out.println("原始数据: " + originalText);
        byte[] plainText = originalText.getBytes(StandardCharsets.UTF_8);

        // 3. 使用公钥加密
//        byte[] encryptedData = encrypt(publicKey, plainText);
        byte[] encryptedData = RsaUtil.encryptLargeData(publicKey, plainText);
        System.out.println("加密结果(Base64): " + Base64.toBase64String(encryptedData));

        // 4. 使用私钥解密
//        byte[] decryptedData = decrypt(privateKey, encryptedData);
        byte[] decryptedData = RsaUtil.decryptLargeData(privateKey, encryptedData);
        System.out.println("解密结果: " + new String(decryptedData, StandardCharsets.UTF_8));
    }

    public static PublicKey loadFromRSACer(String cerBase64) throws Exception {
        // 读取证书文件
        byte[] certBytes = Base64.decode(cerBase64);

        // 创建证书工厂
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");

        // 生成证书对象
        X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(
                new ByteArrayInputStream(certBytes));

        // 获取公钥
        PublicKey publicKey = certificate.getPublicKey();

        // 验证是否为RSA公钥
        if (!"RSA".equals(publicKey.getAlgorithm())) {
            throw new IllegalArgumentException("证书不是RSA类型");
        }

        return publicKey;
    }

    public static PrivateKey loadFromRSAP12(String p12Base64, String password) throws Exception {
        // 加载PKCS12文件
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new ByteArrayInputStream(Base64.decode(p12Base64)), password.toCharArray());

        // 获取别名
        String alias = keyStore.aliases().nextElement();

        // 获取私钥
        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());

        // 验证是否为RSA私钥
        if (!"RSA".equals(privateKey.getAlgorithm())) {
            throw new IllegalArgumentException("密钥不是RSA类型");
        }

        return privateKey;
    }

    public static PrivateKey restorePrivateKey(byte[] privateKeyBytes, String algorithm) throws Exception {
        // algorithm 通常是 "RSA" 或 "EC"
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        return keyFactory.generatePrivate(keySpec);
    }

    public static PublicKey restorePublicKey(byte[] publicKeyBytes, String algorithm) throws Exception {
        // algorithm 应与公钥的算法一致，例如 "RSA" 或 "EC"
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
        return keyFactory.generatePublic(keySpec);
    }

}
